home *** CD-ROM | disk | FTP | other *** search
/ C/C++ Users Group Library 1996 July / C-C++ Users Group Library July 1996.iso / vol_300 / 331_01 / hist.c < prev    next >
Text File  |  1990-06-12  |  8KB  |  298 lines

  1. /*
  2. HEADER:         CUG999.11;
  3. TITLE:          GED (nee QED) screen editor -- part 2;
  4. DATE:           12/19/86;
  5.  
  6. DESCRIPTION:   "Text changing routines for the GED editor. Eg,
  7.                 movechar, insertchar.";
  8. SYSTEM:         MS-DOS;
  9. FILENAME:       GED2.C;
  10. AUTHORS:        G. Nigel Gilbert, James W. Haefner, Mel Tearle, G. Osborn;
  11. COMPILERS:      DeSmet C;
  12. */
  13.  
  14. /*
  15.      e/qed/ged screen editor
  16.  
  17.     (C) G. Nigel Gilbert, MICROLOGY, 1981
  18.            August-December 1981
  19.  
  20.     Modified:  Aug-Dec   1984:   BDS-C 'e'(vers 4.6a) to 'qe' (J.W. Haefner)
  21.                March     1985:   BDS-C 'qe' to DeSmet-C 'qed' (J.W. Haefner)
  22.                May       1986:   converted to ged - Mel Tearle
  23.  
  24.     FILE:      hist.c
  25.  
  26.     FUNCTIONS: undo, pop
  27.  
  28.     PURPOSE:   perform text changing commands
  29.  
  30. */
  31.  
  32.  
  33. #include <stdio.h>
  34. #include <ctype.h>
  35. #include "ged.h"
  36.  
  37.  
  38. /* undoes edits on current line and then from history
  39.  */
  40. undo()
  41. {
  42.     int  l, inicnt, c;
  43.  
  44.     puttext();
  45.     if ( histcnt == 0 )  {
  46.         error( " Nothing to undo " );
  47.         return;
  48.     }
  49.     inicnt = histcnt;
  50.     c = OOPSKEY;            /* do the first one for free */
  51.  
  52.     do {
  53.         vbord1 = MAXINT;
  54.         vbord2 = 0;
  55.         blocking = NO;
  56.  
  57.         switch (c) {
  58.         case OOPSKEY:
  59.         case '-':        /* ctrl key not requeired */
  60.         case '_':
  61.             if (histcnt > 0) {
  62.                 do {
  63.                 l = undoredo(-1);    /* pre decrements histptr */
  64.                 }
  65.                 while ( histcnt > 0  &&  history[histptr].histcomm ==
  66.                 history[ (histptr-1 >= 0) ? histptr-1 : HISTLEN-1 ].histcomm );
  67.  
  68.                 hshow(l);
  69.  
  70.             }
  71.             else {
  72.                 error("Can't undo more.  Redo or escape.  Escape obliterates redo.");
  73.             }
  74.             break;
  75.  
  76.         case '=':
  77.         case '+':  /* same key */
  78.             if (histcnt < inicnt) {
  79.                 do {
  80.                 l = undoredo(1);   /* post increments histptr */
  81.                 }
  82.                 while ( histcnt < inicnt  &&  history[histptr].histcomm ==
  83.                 history[ (histptr-1 >= 0) ? histptr-1 : HISTLEN-1 ].histcomm );
  84.  
  85.                 hshow(l);
  86.             }
  87.             else {
  88.                 error("Can't redo future.  Now in edit mode.");
  89.                 resetpcursor();
  90.                 while (chkbuf() == 0)
  91.                     ;
  92.                 goto leave;
  93.             }
  94.             break;
  95.  
  96.         default:
  97.             error("Bad key.  ^- to undo more,  + or = to redo,  <esc> to resume editing");
  98.             break;
  99.         }
  100.     }
  101.     while ( (c = getkey()) != ESCKEY);
  102.  
  103. leave:;
  104.     blocking = NO;
  105.     putpage();
  106.     blankedmess = YES;
  107.     return;
  108. }
  109.  
  110.  
  111. /* local function */
  112.  
  113. hshow(l)
  114. int l;
  115. {
  116.     int i;
  117.  
  118. /* leave room for the line number. not an error, but show in reverse field */
  119.     hstart(FNPOS);
  120.     error1(" - undo, +/= redo; or <esc> ");
  121.     show_time(1);
  122.  
  123.     if (vbord2 >= vbord1)
  124.         blocking=TRUE;
  125.  
  126. /* moveline requires that the existing physical display agree with memory.
  127.  * They aren't the same at this point if lines within the active display
  128.  * area have been changed.  A complete rewrite is necessary.
  129.  */
  130.     charn = offset + (offset>0);
  131. /* the preferred cursor position is the one that does not cause scrolling */
  132.     cursory += l - cline;
  133. /* re-optimize the cursor if the new location is off-screen */
  134.     if (cursory > SHEIGHT || cursory < topline)
  135.         cursory = topline + (SHEIGHT - topline)/2;
  136. /* but it is more important to see the whole block */
  137.     i = cline;
  138.     cline = l;
  139.     calp();
  140.     cline = i;
  141.     if (vbord2 >= plast)
  142.         cursory += plast - vbord2 -1;  /* limit checked in calp() */
  143.  
  144.     plast = -1;
  145.     moveline(l-cline);
  146.     return;
  147. }
  148. /* --------------------------------------- */
  149. /* local function
  150.  *  direc = 1 to redo, -1 to undo.
  151.  */
  152. int undoredo(direc)
  153. int direc;
  154. {
  155.     int  l, hpage, hoff;
  156.  
  157.     if (direc < 0) {   /* post increment for redo */
  158.         if ( --histptr < 0 )
  159.             histptr = ( HISTLEN - 1 );
  160.         histcnt--;
  161.     }
  162.  
  163.     storehist = NO;
  164.  
  165.     l = history[histptr].histline;
  166.     hpage = history[histptr].histp.page;
  167.     hoff = history[histptr].histp.moffset;
  168.  
  169. /* the following comments apply to an undo step.  The same code is executed
  170.  * for the redo, but then the undo/redo roles change.  The function is
  171.  * fully symmetrical between redo/undo, and except for a wasted byte
  172.  * in the inject() is indefinately reversible.
  173.  */
  174.  
  175.     switch ( history[histptr].histtype )  {
  176.  
  177.     case HISTINSERT:
  178.         history[histptr].histp.moffset = tp[l].moffset;  /* prepare for redo */
  179.         history[histptr].histp.page = tp[l].page; /* prepare for redo */
  180.         history[histptr].histtype = HISTDELETE;   /* prepare for redo */
  181.         deltp(l,1);                               /* undo */
  182.         if (l <= vbord2)
  183.             vbord2--;
  184.         break;
  185.     case HISTDELETE:
  186.         inject(l-1,"");                         /* undo */
  187.         tp[l].moffset = hoff;                   /* undo */
  188.         tp[l].page = hpage;                     /* undo */
  189.         history[histptr].histtype = HISTINSERT; /* prepare for redo */
  190.         if (vbord2 >= l)
  191.             vbord2++;
  192.         if (l > vbord2)
  193.             vbord2 = l;
  194.         if (l < vbord1)
  195.             vbord1 = l;
  196.         break;
  197.     case HISTREPLACE:
  198.  
  199.         history[histptr].histp.moffset = tp[l].moffset; /* prepare for redo */
  200.         history[histptr].histp.page = tp[l].page; /* prepare for redo */
  201.         tp[l].page = hpage;                      /* undo */
  202.         tp[l].moffset= hoff;                     /* undo */
  203.  
  204.         if (l > vbord2)
  205.             vbord2 = l;
  206.         if (l < vbord1)
  207.             vbord1 = l;
  208.         break;
  209.     }
  210.     if (direc > 0) {
  211.         if (++histptr >= HISTLEN)
  212.             histptr = 0;
  213.         histcnt++;
  214.     }
  215.  
  216.     return l;
  217. }
  218. /* --------------------------------------- */
  219.  
  220. /* pop the last deleted line from the history buffer.
  221.  * This is a prelimenary implementation of stack operations and is
  222.  * something of a kludge.  The stack needs its own table.  It can
  223.  * use the text of the lines in the histroy buffer, though.
  224.  * This "stack" will be overwritten after 100 editing operations.
  225.  * Pops can be undone, so a different area of the data base used here
  226.  * is modifed by addhistory() when a pop is performed.
  227.  * Editing which occurs later than the pop can be undone without conflict,
  228.  * provided there is not too much of it.
  229.  */
  230.  
  231. pop(mode)
  232. int mode;
  233. {
  234.     int  onpage;     /* flag for changes to current screen */
  235.     int  l, slot;
  236.     int h0, h1, h2;
  237.     char *ptr;
  238.     char *gethist();
  239.  
  240.     puttext();  /* must be done before the stack test */
  241.     if ( stkcnt == 0 )  {
  242.         error( " Stack empty " );
  243.         return;
  244.     }
  245.     h0 = stkptr;
  246.     h1 = stkcnt;
  247.     h2 = 0;
  248.     do {
  249.         if ( --stkptr < 0 )
  250.             stkptr = ( HISTLEN - 1 );
  251.         stkcnt--;
  252.         ptr = gethist(history[stkptr].histp.page,history[stkptr].histp.moffset);
  253.         switch ( history[stkptr].histtype )  {
  254.         case HISTREPLACE:
  255.             break;
  256.         case HISTINSERT:
  257.             break;
  258.         case HISTDELETE:
  259.             h2 = 1;
  260.             break;
  261.         }
  262.  
  263.     }
  264.     while ( !h2 && stkcnt &&  history[stkptr].histcomm ==
  265.         history[( stkptr-1 < 0 ? HISTLEN-1 : stkptr-1) ].histcomm );
  266.     if (mode == 1) {
  267.         stkptr = h0;  /* copy and pop.  restore to original state. */
  268.         stkcnt = h1;
  269.     }
  270.     if (!h2)
  271.         error( " Stack empty " );
  272.     else {
  273.         vbord1=cline;
  274.         vbord2=cline;
  275.         blocking=TRUE;
  276.         scrolldown(cursory);
  277.         sync(offset + (offset>0));
  278.         putline(cline, cursory, ptr);
  279.         putlineno(cline);   /* new col no */
  280.         resetpcursor();
  281.  
  282. /* do the slow work while waiting for a keystroke, otherwise the next
  283.    operation is delayed
  284.  */
  285.         inject(cline-1,ptr);
  286.         calp();  /* plast may have changed */
  287.         while (chkbuf()==0)   /* wait for any